View Javadoc

1   /*
2    * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted under the terms of either of the following
6    * Open Source licenses:
7    *
8    * The GNU General Public License, version 2, or any later version, as
9    * published by the Free Software Foundation
10   * (http://www.fsf.org/copyleft/gpl.html);
11   *
12   *  or
13   *
14   * The Semiotek Public License (http://webmacro.org/LICENSE.)
15   *
16   * This software is provided "as is", with NO WARRANTY, not even the
17   * implied warranties of fitness to purpose, or merchantability. You
18   * assume all risks and liabilities associated with its use.
19   *
20   * See www.webmacro.org for more information on the WebMacro project.
21   */
22  
23  /***
24   * @author Brian Goetz
25   */
26  
27  package org.webmacro.parser;
28  
29  import org.webmacro.engine.BlockBuilder;
30  
31  /***
32   * ParserBlockBuilder extends BlockBuilder, and should only be used by
33   * the WMParser_impl parser.  It adds methods for eating trailing
34   * <WHITESPACE>  or  <WHITESPACE> <NL> <WHITESPACE>  that precede directives.
35   * It assumes that literal text will not span elements (true for the
36   * current parser) so if the parser changes, this will need to change too.
37   */
38  
39  
40  public class ParserBlockBuilder extends BlockBuilder
41  {
42  
43      private int literalMark = 0;
44  
45      public ParserBlockBuilder ()
46      {
47          super();
48      }
49  
50      public ParserBlockBuilder (String name)
51      {
52          super(name);
53      }
54  
55      /*** Mark the last character in the block as being a literal (quoted
56       * with backslash) so we don't eat trailing quoted whitespace.
57       */
58      final public void markLiteral ()
59      {
60          literalMark = size();
61      }
62  
63      private final static boolean isSpaceChar (char c)
64      {
65          return (c == ' ' || c == '\t');
66      }
67  
68      private final static int eatWs (String s, int pos)
69      {
70          while (pos >= 0 && isSpaceChar(s.charAt(pos)))
71              pos--;
72          return pos;
73      }
74  
75      private final static int eatOneWs (String s, int pos)
76      {
77          if (pos >= 0 && isSpaceChar(s.charAt(pos)))
78              pos--;
79          return pos;
80      }
81  
82      private final static int eatNl (String s, int pos)
83      {
84          if (pos >= 0)
85          {
86              if (s.charAt(pos) == '\r')
87                  pos--;
88              else if (s.charAt(pos) == '\n')
89              {
90                  pos--;
91                  if (pos >= 0 && s.charAt(pos) == '\r')
92                      pos--;
93              }
94          }
95          return pos;
96      }
97  
98      final public void eatTrailingWs ()
99      {
100         int i, j;
101 
102         i = size() - 1;
103         if (i < 0 || i + 1 == literalMark)
104             return;
105 
106         Object o = elementAt(i);
107         if (!(o instanceof String))
108             return;
109         String s = (String) o;
110         j = eatWs(s, s.length() - 1);
111 
112         if (j < 0)
113             remove(i);
114         else if (j < s.length() - 1)
115             setElementAt(s.substring(0, j + 1), i);
116         markLiteral();
117     }
118 
119 
120     final public void eatTrailingWsNl ()
121     {
122         int i, j;
123 
124         i = size() - 1;
125         if (i < 0 || i + 1 == literalMark)
126             return;
127 
128         Object o = elementAt(i);
129         if (!(o instanceof String))
130             return;
131         String s = (String) o;
132         j = eatWs(s, s.length() - 1);
133         j = eatNl(s, j);
134 
135         if (j < 0)
136             remove(i);
137         else if (j < s.length() - 1)
138             setElementAt(s.substring(0, j + 1), i);
139         markLiteral();
140     }
141 
142     final public void eatTrailingWsNlWs ()
143     {
144         int i, j;
145 
146         i = size() - 1;
147         if (i < 0 || i + 1 == literalMark)
148             return;
149 
150         Object o = elementAt(i);
151         if (!(o instanceof String))
152             return;
153         String s = (String) o;
154         j = eatWs(s, s.length() - 1);
155         j = eatNl(s, j);
156         j = eatWs(s, j);
157 
158         if (j < 0)
159             remove(i);
160         else if (j < s.length() - 1)
161             setElementAt(s.substring(0, j + 1), i);
162         markLiteral();
163     }
164 
165     final public void eatOneWs ()
166     {
167         int i, j;
168 
169         i = size() - 1;
170         if (i < 0 || i + 1 == literalMark)
171             return;
172 
173         Object o = elementAt(i);
174         if (!(o instanceof String))
175             return;
176         String s = (String) o;
177         j = eatOneWs(s, s.length() - 1);
178 
179         if (j < 0)
180             remove(i);
181         else if (j < s.length() - 1)
182             setElementAt(s.substring(0, j + 1), i);
183         markLiteral();
184     }
185 
186     final public void eatLeadingWsNl ()
187     {
188         int i, j, l;
189 
190         i = size() - 1;
191         if (i < 0 || i + 1 == literalMark)
192             return;
193 
194         Object o = elementAt(i);
195         if (!(o instanceof String))
196             return;
197         String s = (String) o;
198         j = 0;
199         l = s.length();
200         while (j < l && isSpaceChar(s.charAt(j)))
201             j++;
202         if (j < l)
203         {
204             if (s.charAt(j) == '\r')
205                 j++;
206             else if (s.charAt(j) == '\n')
207             {
208                 j++;
209                 if (j < l && s.charAt(j) == '\r')
210                     j++;
211             }
212         }
213 
214         if (j >= l)
215             remove(i);
216         else if (j > 0)
217             setElementAt(s.substring(j), i);
218         markLiteral();
219     }
220 
221     final public boolean directiveOk ()
222     {
223         if (size() == 0 || size() == literalMark)
224             return true;
225         else
226         {
227             Object o = elementAt(size() - 1);
228             
229             // NOTE: the test for a zero length string in the following 'if' is 
230             // a work-around for a bug parsing an explicit #begin followed 
231             // immediately by another directive, eg, 
232             // #if ($x) #begin #set $y=0 #end
233             // This can be removed when/if this bug is fixed 
234             // Keats 8-Aug-2003
235             if (!(o instanceof String) || (((String)o).length() == 0))
236                 return true;
237             else
238             {
239                 String s = (String) o;
240                 char ch = s.charAt(s.length() - 1);
241                 if (ch == '=' || ch == '\'' || ch == '\"' || ch == ':'
242                         || Character.isLetterOrDigit(ch))
243                     return false;
244             }
245         }
246         return true;
247     }
248 }